package com.bjb.vr.common.utils;

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bjb.vr.common.constant.CanalConstant;
import com.bjb.vr.common.dto.ExecutedSql;
import com.bjb.vr.common.dto.SyncData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @description:
 * @author: hujingbo
 * @create: 2022-12-09 10:37
 **/
@Slf4j
public class CanalTool {

    private static final String QUERY_STATEMENT = "SELECT * FROM `xr-platform`.`executed_sql` WHERE md5 = ";
    private static final String DELETE_STATEMENT = "DELETE FROM `xr-platform`.`executed_sql` WHERE md5 = ";
    private static final String CLEAN_STATEMENT = "DELETE FROM `xr-platform`.`executed_sql` WHERE gmt_create <= ";
    private static final String CLEAN_SYNC_STATEMENT = "DELETE FROM `xr-platform`.`sync_data` WHERE gmt_create <= ";

    /**
     * 解析SQL语句
     *
     * @param object
     * @return
     */
    public static String parseSqlHandle(JSONObject object) {
        String eventType = (String) object.get("type");
        String statement = "";
        if (CanalConstant.DELETE.equals(eventType)) {
            statement = StatementUtil.saveDeleteSql(object);
        } else if (CanalConstant.UPDATE.equals(eventType)) {
            statement = StatementUtil.saveUpdateSql(object);
        } else if (CanalConstant.INSERT.equals(eventType)) {
            statement = StatementUtil.saveInsertSql(object);
        } else {
            StringBuilder builder = new StringBuilder();
            statement = builder.append(object.getString("sql")).append(";").toString();
        }
        return statement;
    }

    /**
     * 获取查询SQL
     *
     * @param statementMd5
     * @return
     */
    public static String getQueryStatement(String statementMd5) {
        return QUERY_STATEMENT + "'" + statementMd5 + "';";
    }

    /**
     * 获取删除SQL
     *
     * @param statementMd5
     * @return
     */
    public static String getDeleteStatement(String statementMd5) {
        return DELETE_STATEMENT + "'" + statementMd5 + "';";
    }

    /**
     * 获取清理执行过的SQL语句
     *
     * @param startTime
     * @return
     */
    public static String getCleanStatement(String startTime) {
        return CLEAN_STATEMENT + "'" + startTime + "';";
    }

    /**
     * 获取清理不同步的SQL语句
     *
     * @param startTime
     * @return
     */
    public static String getCleanSyncStatement(String startTime) {
        return CLEAN_SYNC_STATEMENT + "'" + startTime + "';";
    }

    /**
     * 保存数据到sync_data表中
     *
     * @param object
     * @param statement
     * @param tenantId
     * @return
     */
    public static SyncData buildSyncDataEntity(JSONObject object, String statement, String tenantId) {
        String eventType = object.getString(CanalConstant.TYPE);
        String dbName = object.getString(CanalConstant.DB);
        String tableName = object.getString(CanalConstant.TABLE);
        JSONArray jsonArray = object.getJSONArray(CanalConstant.DATA);
        String statementMd5 = MD5.create().digestHex(statement);
        // 封装实体类
        SyncData syncData = new SyncData();
        // 设置事件类型
        if (StringUtils.isBlank(eventType)) {
            String type = object.getString(CanalConstant.TYPE);
            syncData.setEventType(type);
        } else {
            syncData.setEventType(eventType);
        }
        // 设置数据ID
        if (Objects.nonNull(jsonArray)) {
            Long dataId = jsonArray.getJSONObject(0).getObject(CanalConstant.DATA_ID, Long.class);
            syncData.setDataId(dataId);
        } else {
            Long dataId = object.getObject("dataId", Long.class);
            syncData.setDataId(dataId);
        }
        syncData.setMd5(statementMd5);
        syncData.setDbName(dbName);
        syncData.setTenantId(tenantId);
        syncData.setTableName(tableName);
        syncData.setStatement(statement);
        syncData.setGmtCreate(LocalDateTime.now());
        return syncData;
    }

    /**
     * 保存数据到executed_sql表中
     *
     * @param object
     * @param statement
     * @param tenantId
     * @return
     */
    public static ExecutedSql buildExecuteEntity(JSONObject object, String statement, String tenantId) {
        String eventType = object.getString(CanalConstant.EVENT_TYPE);
        String dbName = object.getString(CanalConstant.DB);
        String tableName = object.getString(CanalConstant.TABLE);
        JSONArray jsonArray = object.getJSONArray(CanalConstant.DATA);
        String statementMd5 = MD5.create().digestHex(statement);
        // 封装实体类
        ExecutedSql executedSqlEntity = new ExecutedSql();
        // 设置事件类型
        if (StringUtils.isBlank(eventType)) {
            String type = object.getString(CanalConstant.TYPE);
            executedSqlEntity.setEventType(type);
        } else {
            executedSqlEntity.setEventType(eventType);
        }
        // 设置数据ID
        if (Objects.nonNull(jsonArray)) {
            Long dataId = jsonArray.getJSONObject(0).getObject(CanalConstant.DATA_ID, Long.class);
            executedSqlEntity.setDataId(dataId);
        } else {
            Long dataId = object.getObject("dataId", Long.class);
            executedSqlEntity.setDataId(dataId);
        }
        executedSqlEntity.setTenantId(tenantId);
        executedSqlEntity.setStatement(statement);
        executedSqlEntity.setMd5(statementMd5);
        executedSqlEntity.setDbName(dbName);
        executedSqlEntity.setTableName(tableName);
        executedSqlEntity.setGmtCreate(LocalDateTime.now());
        return executedSqlEntity;
    }
}
